<?php

namespace app\api\controller;

use app\essayhandle\controller\Addessay;
use GuzzleHttp\Client;
use think\Cache;
use think\cache\driver\Redis;
use think\Config;
use think\Db;
use think\Exception;
use WebGeeker\Validation\Validation;

//登录相关
class Login
{
    //发送验证码
    public function getPhoneCode()
    {
        //获取验证码
        try {

            Validation::validate($_GET, [
                "phone" => "Required|Regexp:/^1(3[0-9]|4[579]|5[0-35-9]|7[0135678]|8[0-9]|66|9[89])\d{8}$/"
            ]);

            //发送短信
            $this->sendPhoneCode($_GET['phone']);

        } catch (\Exception $exception) {
            errorBack($exception);
        }
    }

    //发送手机号
    public function sendPhoneCode($phone)
    {
        //必填,请参考"开发准备"获取如下数据,替换为实际值
        $url = 'https://rtcsms.cn-north-1.myhuaweicloud.com:10743/sms/batchSendSms/v1'; //APP接入地址+接口访问URI
        $APP_KEY = 'm97WWjK5FtIV7h29jsnWCWDb4I8e'; //APP_Key
        $APP_SECRET = 'F13400QeCtVjUQ5Vm74Sj8zIw805'; //APP_Secret
        $sender = '8819080633619'; //国内短信签名通道号或国际/港澳台短信通道号
        $TEMPLATE_ID = '8856354b9b7e495fb6bd933882b9f9db'; //模板ID

//条件必填,国内短信关注,当templateId指定的模板类型为通用模板时生效且必填,必须是已审核通过的,与模板类型一致的签名名称
//国际/港澳台短信不用关注该参数
        $signature = "企智未来"; //签名名称

//必填,全局号码格式(包含国家码),示例:+8615123456789,多个号码之间用英文逗号分隔
        $receiver = $phone; //短信接收人号码

//选填,短信状态报告接收地址,推荐使用域名,为空或者不填表示不接收状态报告
        $statusCallback = 'http://sms.rpa-cn.com/getStatus.php';

        /**
         * 选填,使用无变量模板时请赋空值 $TEMPLATE_PARAS = '';
         * 单变量模板示例:模板内容为"您的验证码是${NUM_6}"时,$TEMPLATE_PARAS可填写为 '["369751"]'
         * 双变量模板示例:模板内容为"您有${NUM_2}件快递请到${TXT_20}领取"时,$TEMPLATE_PARAS可填写为'["3","人民公园正门"]'
         * ${DATE}${TIME}变量不允许取值为空,${TXT_20}变量可以使用英文空格或点号替代空值,${NUM_6}变量可以使用0替代空值
         * 查看更多模板格式规范:产品介绍>模板和变量规范
         * @var string $TEMPLATE_PARAS
         */
        //验证码(4位数)
        $phoneCode = rand(1000, 9999);
        $TEMPLATE_PARAS = "['$phoneCode']"; //模板变量
        $client = new Client();
        $response = $client->request('POST', $url, [
            'form_params' => [
                'from' => $sender,
                'to' => $receiver,
                'templateId' => $TEMPLATE_ID,
                'templateParas' => $TEMPLATE_PARAS,
                'statusCallback' => $statusCallback,
//            'signature' => $signature //使用国内短信通用模板时,必须填写签名名称
            ],
            'headers' => [
                'Authorization' => 'WSSE realm="SDP",profile="UsernameToken",type="Appkey"',
                'X-WSSE' => $this->buildWsseHeader($APP_KEY, $APP_SECRET)
            ],
            'verify' => false //为防止因HTTPS证书认证失败造成API调用失败，需要先忽略证书信任问题
        ]);

        $result = json_decode($response->getBody(), true);

        if ($result['code'] === '000000') {

            $redis = new \Predis\Client();

            $redis->select(1);

            $redis->setex($phone, 1800, $phoneCode);


            $msg = '验证码发送成功';
            successBack([],$msg);
        } else {
            //手动抛出异常
            throw new Exception('验证码发送失败', 1);
        }
    }

    /**
     * 构造X-WSSE参数值
     * @param string $appKey
     * @param string $appSecret
     * @return string
     */
    private function buildWsseHeader(string $appKey, string $appSecret)
    {
        $now = date('Y-m-d\TH:i:s\Z'); //Created
        $nonce = uniqid(); //Nonce
        $base64 = base64_encode(hash('sha256', ($nonce . $now . $appSecret))); //PasswordDigest
        return sprintf("UsernameToken Username=\"%s\",PasswordDigest=\"%s\",Nonce=\"%s\",Created=\"%s\"",
            $appKey, $base64, $nonce, $now);

    }


    //验证码登录
    public function userPhoneCodeLogin()
    {
        try {
            Validation::validate($_GET, [
                "phone" => "Required|Regexp:/^1(3[0-9]|4[579]|5[0-35-9]|7[0135678]|8[0-9]|66|9[89])\d{8}$/|>>>:手机号格式错误",
                "phoneCode" => "Required|Str|Numbers|StrLen:4|>>>:验证码格式错误",
                "deviceToken" => "Str"
            ]);

            Db::startTrans();

            $phone = $_GET['phone'];

            $phoneCode = $_GET['phoneCode'];

            if(isset($_GET['deviceToken'])){
                $deviceToken = $_GET['deviceToken'];
            }else{
                $deviceToken = null;
            }


            //先判断验证码正确吗
            $redis = new \Predis\Client();

            $redis->select(1);

            $result = $redis->get($phone);

            if (!$result) {
                throw new Exception('请先获取验证码');
            } else {
                if ($result != $phoneCode) {
                    throw new Exception('验证码错误', 1002);
                }
            }


            $this->phoneLogin($phone, $deviceToken);
        } catch (\Exception $exception) {
            Db::rollback();
            errorBack($exception);
        }
    }

    //验证码验证通过后,一键登录获取手机号后，来判断用户是不是已经注册，没有注册返回
    private function phoneLogin($phone, $deviceToken)
    {
        //验证码正确 , 看看是注册还是直接返回uid
        $user_obj = Db::name('user');

        //判断当前手机号有没有注册
        $user_info = $user_obj->where(['phone' => $phone])->field('user_id')->field('user_id,user_unique')->find();

        if (!$user_info) {
            //数据不存在(新注册账号)
            //echo '注册新号';
            $addData = [];
            $addData['nick_name'] = '飞言' . $phone;
            $addData['phone'] = $phone;
            $addData['register_time'] = date('Y-m-d H:i:s');

            if($deviceToken){
                $addData['device_token'] = $deviceToken;
                $addData['device_token_md5'] = md5($deviceToken);
            }


            //插入数据到数据库
            $user_id = $user_obj->insertGetId($addData);


            if (!$user_id) {
                throw new Exception('登录失败', 1);
            }


            $user_unique = md5(createUserToken(['user_id' => $user_id]));

            $result = $user_obj->where(['user_id' => $user_id])->update(['user_unique' => $user_unique]);

            if ($result != 1) {
                throw new Exception('登录失败', 1);
            }

            //上传数据到智能推荐用户表
            //上传用户信息到智能推荐
            $arr = [];

            $add['fields'] = [];

            $arr['fields']['user_id_type'] = 1;

            $arr['fields']['user_id'] = $user_unique;

            if($deviceToken){
                $arr['fields']['imei'] = $addData['device_token_md5'];
            }


            $arr['fields']['third_user_type'] = 'phone';

            $arr['fields']['gender'] = 'unknown';

            $arr['fields']['country'] = 'CHN';

            $arr['fields']['source'] = '手机号注册';

            $arr['fields']['phone_md5'] = md5($phone);

            $arr['cmd'] = 'add';

            $content = [];

            $content[] = $arr;

            $addessayObj = new Addessay();

            //先隐藏上传智能推荐

            $result = $addessayObj->uploadingAirec($content, 'user');

            if (!$result) {
                throw new Exception('登录失败', 1);
            }
        } else {
            $user_unique = $user_info['user_unique'];
            $user_id = $user_info['user_id'];
        }

        Db::commit();
        //返回给前端的数据
        successBack(['user_token' => createUserToken(['user_id' => $user_id]), 'user_unique' => $user_unique], '登录成功');
    }


    //微信登录(返回用户的唯一标识)
    public function wxLogin()
    {

        try {
            Validation::validate($_GET, [
                "uid" => "Required|IntGe:1|>>>:友盟微信登录用户标识不存在/错误",
                "name" => "Required|Str|>>>:友盟微信登录用户昵称不存在/错误",
                "iconurl" => "Required|Str|>>>:友盟微信登录用户头像不存在/错误",
                "deviceToken" => "Required|Str"
            ]);

            Db::commit();

            //此处的uid是微信登录返回的唯一标识
            $uid = $_GET['uid'];
            //昵称
            $nick_name = $_GET['name'];
            //头像
            $iconurl = $_GET['iconurl'];
            //设备号
            $deviceToken = $_GET['deviceToken'];

            $user_obj = Db::name('user');
            //判断这个uid是不是已经存在
            $user_info = $user_obj->where(['uid' => $uid])->field('user_id,user_unique')->find();

            if (!$user_info) {

                //新建用户
                $addData = [];
                $addData['uid'] = $uid;
                $addData['head_img'] = $iconurl;

                //判断当前昵称是不是已经存在
                $nick_name_result = $user_obj->where(['nick_name' => $nick_name])->count();
                if ($nick_name_result) {
                    $addData['nick_name'] = $nick_name . base64_encode($uid);
                } else {
                    $addData['nick_name'] = $nick_name;
                }

                $addData['device_token'] = $deviceToken;
                $addData['device_token_md5'] = md5($deviceToken);

                $addData['register_time'] = date('Y-m-d H:i:s');

                $user_id = $user_obj->insertGetId($addData);


                if (!$user_id) {
                    throw new Exception('登录失败', 1);
                }


                $user_unique = md5(createUserToken(['user_id' => $user_id]));

                $result = $user_obj->where(['user_id' => $user_id])->update(['user_unique' => $user_unique]);

                if ($result != 1) {
                    throw new Exception('登录失败', 1);
                }

                //上传数据到智能推荐用户表
                //上传用户信息到智能推荐
                $arr = [];

                $add['fields'] = [];

                $arr['fields']['user_id_type'] = 1;

                $arr['fields']['user_id'] = $user_unique;

                $arr['fields']['imei'] = $addData['device_token_md5'];

                $arr['fields']['third_user_type'] = 'wxchat';

                $arr['fields']['gender'] = 'unknown';

                $arr['fields']['country'] = 'CHN';

                $arr['fields']['source'] = '手机号注册';

                $arr['fields']['third_user_name'] = $addData['nick_name'];

                $arr['cmd'] = 'add';

                $content = [];

                $content[] = $arr;

                $addessayObj = new Addessay();

                $result = $addessayObj->uploadingAirec($content, 'user');

                if (!$result) {
                    throw new Exception('登录失败', 1);
                }

            } else {
                $user_unique = $user_info['user_unique'];
                $user_id = $user_info['user_id'];
            }


            Db::commit();
            //返回给前端的数据
            successBack(['user_token' => createUserToken(['user_id' => $user_id]), 'user_unique' => $user_unique], '登录成功');

        } catch (\Exception $exception) {
            Db::rollback();
            errorBack($exception);
        }
    }

    //一键登录
    //友盟一键登录,获取了手机号
    public function onekeyLogin()
    {
        try {

            Validation::validate($_GET, [
                "token" => "Required|Str|>>>:token不存在/错误",
                "device_type" => "Required|IntIn:1,2|>>>:设备类型不存在/错误",
                "deviceToken" => "Required|Str"
            ]);

            $device_type = $_GET['device_type'];

            $token = $_GET['token'];

            $deviceToken = $_GET['deviceToken'];

            $androidAppKey = '5e6f806b978eea0774044b93';

            $iosAppKey = '5e74208e978eea0774044e6d';

            $url = "https://verify5.market.alicloudapi.com/api/v1/mobile/info?appkey=";
            switch ($device_type) {
                case 1:
                    $url .= $androidAppKey;
                    $appkey = $androidAppKey;
                    break;

                case 2:
                    $url .= $iosAppKey;
                    $appkey = $iosAppKey;
                    break;
            }

            $curl = curl_init();
            //设置抓取的url
            curl_setopt($curl, CURLOPT_URL, $url);
            //设置头文件的信息作为数据流输出
            //curl_setopt($curl, CURLOPT_HEADER, 1);


            $header['Content-Type'] = 'application/json; charset=UTF-8';
            $header['Accept'] = 'application/json';
            //$header['X-Ca-Request-Mode'] = 'debug';
            $header['X-Ca-Version'] = 1;

            $header['X-Ca-Stage'] = 'RELEASE';
            $header['X-Ca-Key'] = '203786807';
            $header['X-Ca-Nonce'] = getMillisecond();
            $header['X-Ca-Timestamp'] = getMillisecond();
            $header['X-Ca-Signature-Headers'] = 'X-Ca-Key,X-Ca-Nonce,X-Ca-Signature-Headers,X-Ca-Stage,X-Ca-Timestamp,X-Ca-Version';

            require_once VENDOR_PATH . 'UmengSign/Util/Autoloader.php';
            $sign = \SignUtil::Sign(
                '/api/v1/mobile/info',
                'post',
                'mwghcshssdxu7u4w05hf2s8ifms8q89p',
                $header,
                ['appkey' => $appkey],
                [],
                ['X-Ca-Key', 'X-Ca-Nonce', 'X-Ca-Signature-Headers', 'X-Ca-Stage', 'X-Ca-Timestamp', 'X-Ca-Version']);

            $h = array(
                'Content-Type:' . 'application/json; charset=UTF-8',
                'Accept:' . 'application/json',
                'X-Ca-Nonce:' . $header['X-Ca-Nonce'],
                'X-Ca-Version:' . '1',
                'X-Ca-Signature-Headers:' . $header['X-Ca-Signature-Headers'],
                'X-Ca-Stage:' . 'RELEASE',
                'X-Ca-Key:' . '203786807',
                'X-Ca-Timestamp:' . $header['X-Ca-Timestamp'],
                'X-Ca-Signature:' . $sign
            );

            //设置请求头
            curl_setopt($curl, CURLOPT_HTTPHEADER, $h);
            //设置获取的信息以文件流的形式返回，而不是直接输出。
            curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
            //curl_setopt($curl, CURLOPT_HEADER, true);
            //设置post方式提交
            curl_setopt($curl, CURLOPT_POST, 1);
            //设置post数据
            $post_data = json_encode(['token' => $token]);
            curl_setopt($curl, CURLOPT_POSTFIELDS, $post_data);
            //执行命令
            $data = json_decode(curl_exec($curl), true);
            //显示获得的数据
            //$httpCode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
            //var_dump($httpCode);
            //关闭URL请求
            curl_close($curl);

            if ($data['success']) {
                $phone = $data['data']['mobile'];

                $this->phoneLogin($phone, $deviceToken);

            } else {
                throw new Exception($data['code'] . $data['message']);
            }
        } catch (\Exception $exception) {
            errorBack($exception);
        }
    }

    //上传device_token生成一个用户
    public function uploadingDeviceToken($device_token)
    {
        try {

            if (!$device_token) {
                throw new Exception('device_token值不能为空字符串');
            }

            //判断当前device_token是不是已经注册
            $user_obj = Db::name('user');

            Db::startTrans();

            $addData = [];
            $addData['device_token'] = $device_token;
            $addData['device_token_md5'] = md5($device_token);
            $addData['register_time'] = date('Y-m-d H:i:s');
            $addData['user_type'] = 0;
            $addData['user_unique'] = md5(createUserToken(['device' => $device_token]));

            $user_id = $user_obj->insertGetId($addData);

            if (!$user_id) {
                throw new Exception('使用device_token创建用户失败');
            }

            //上传用户信息到智能推荐
            $arr = [];

            $add['fields'] = [];

            $arr['fields']['user_id_type'] = 1;

            $arr['fields']['imei'] = $addData['device_token_md5'];

            $arr['fields']['third_user_type'] = 'device';

            $arr['fields']['gender'] = 'unknown';

            $arr['fields']['country'] = 'CHN';

            $arr['fields']['source'] = '设备device_token注册';

            $arr['cmd'] = 'add';

            $content = [];

            $content[] = $arr;

            $addessayObj = new Addessay();

            $result = $addessayObj->uploadingAirec($content, 'user');

            if ($result) {

                Db::commit();
                return $user_id;
            } else {
                throw new Exception('使用device_token创建用户失败');
            }

        } catch (\Exception $exception) {
            Db::rollback();
            errorBack($exception);
        }
    }

    //生成测试的user_token
    public function createTestUserToken()
    {
        echo createUserToken(['user_id' => 42]);
    }

    //飞言创作端上传用户的昵称头像接口
    public function creationUpdateUser(){
        try {
            // 验证（如果验证不通过，会抛出异常)
            Validation::validate($_GET, [
                "nick_name" => "Required|Str|StrLenGe:1",
                "intro"=>'Required|Str|StrLenGe:1',
                "head_img"=>'Required|Str|StrLenGe:1',
                "user_unique"=>'Required|Str|StrLenGe:1'
            ]);

            //昵称
            $nick_name = trim($_GET['nick_name']);

            //简介
            $intro = trim($_GET['intro']);

            //头像
            $head_img = trim($_GET['head_img']);

            $user_unique = trim($_GET['user_unique']);


            //判断用户是不是已经存在
            $user_obj = Db::name('user');


            $result = $user_obj->where(['user_unique'=>$user_unique])->field('user_id')->find();

            if(!$result){
                throw new Exception('用户不存在');
            }


            //查看当前昵称是不是存在
            $result = $user_obj->where(['nick_name'=>$nick_name])->field('user_id')->find();

            if($result){
                throw new Exception('昵称已经存在');
            }

            $add_data = [];

            $add_data['nick_name'] = $nick_name;

            $add_data['intro'] = $intro;

            $add_data['head_img'] = $head_img;


            Db::startTrans();

            $user_id = $user_obj->where(['user_unique'=>$user_unique])->update($add_data);

            if(!$user_id){
                throw new Exception('更新失败');
            }

            Db::commit();
            successBack([],'更新成功');
        }catch (\Exception $exception){
            Db::rollback();
            errorBack($exception);
        }
    }


    //上传用户活跃状态
    public function getUserActive(){
        //获取用户的user_token
        try {
            Validation::validate($_GET, [
                "usertoken" => "Required|Str|StrLenGe:1"
            ]);

            $arr = verification($_GET['usertoken']);

            //获取到的user_id
            $user_id = $arr['user_data']->user_id;

            //获取当前用户的
            Db::name('user')->where(['user_id' => $user_id])->field('user_id')->findOrFail();

            //插入队列
            //添加对列到队列中(status:用户的操作,result_status处理之前的状态)
            add_queue('app\queueHandle\News', 'News',
                ['user_id'=>$user_id,'type'=>'feedHandle']);

        }catch (\Exception $exception){
            errorBack($exception);
        }
    }

    public function test(){
        var_dump($this->uploadingDeviceToken('王玉烽测试device_token'));
    }
}